package org.cloudie.docs.editor.client.managers;

import org.cloudie.docs.editor.client.behaviors.HasDropBehavior;
import org.cloudie.docs.editor.client.behaviors.HasReceiveBehavior;

import com.allen_sauer.gwt.dnd.client.DragContext;
import com.allen_sauer.gwt.dnd.client.VetoDragException;
import com.allen_sauer.gwt.dnd.client.drop.SimpleDropController;
import com.google.gwt.user.client.ui.Widget;

public class DropReceiveManager extends SimpleDropController {

  private Widget dropTarget;

  public DropReceiveManager(Widget dropTarget) {
    super(dropTarget);
    this.dropTarget = dropTarget;
  }

  @Override
  public void onDrop(DragContext context) {
    super.onDrop(context);
    int x = context.desiredDraggableX - dropTarget.getAbsoluteLeft();
    int y = context.desiredDraggableY - dropTarget.getAbsoluteTop();
    if (context.draggable instanceof HasDropBehavior) {
      ((HasDropBehavior) context.draggable).onDropped(dropTarget, x, y);
    }
    if (dropTarget instanceof HasReceiveBehavior) {
      ((HasReceiveBehavior) dropTarget).onReceive(context.draggable, x, y);
    }
  }

  @Override
  public void onEnter(DragContext context) {
    super.onEnter(context);
    try {
      onPreviewDrop(context, false);
      dropTarget.addStyleDependentName("drop-allowed");
    } catch(VetoDragException x) {
      dropTarget.addStyleDependentName("drop-denied");
    }
  }

  @Override
  public void onLeave(DragContext context) {
    super.onLeave(context);
    dropTarget.removeStyleDependentName("drop-allowed");
    dropTarget.removeStyleDependentName("drop-denied");
  }

  @Override
  public void onPreviewDrop(DragContext context) throws VetoDragException {
    onPreviewDrop(context, true);
  }
  
  protected void onPreviewDrop(DragContext context, boolean isFinal) throws VetoDragException {
    super.onPreviewDrop(context);
    if (context.draggable instanceof HasDropBehavior) {
      HasDropBehavior dropped = (HasDropBehavior) context.draggable;
      if (!dropped.allowsDropping() || !dropped.allowsDropping(dropTarget)) {
    	dropped.onDropCanceled();
    	throw new VetoDragException();
      }
    } else {
      throw new VetoDragException();
    }
    if (dropTarget instanceof HasReceiveBehavior) {
      HasReceiveBehavior receiver = (HasReceiveBehavior) dropTarget;
      if (!receiver.acceptsReceives() || !receiver.acceptsReceives(context.draggable, isFinal)) {
        throw new VetoDragException();
      }
    } else {
      throw new VetoDragException();
    }
  }
	
}
